package yl.hs.bmipfull.service.production.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import yl.hs.bmipfull.annotations.DBTable;
import yl.hs.bmipfull.daos.material.IPurchaseSystemLogDao;
import yl.hs.bmipfull.daos.production.IProductionDataTagDao;
import yl.hs.bmipfull.daos.production.IProductionDispatchLogDao;
import yl.hs.bmipfull.daos.salemanage.ISaleSysTagsDao;
import yl.hs.bmipfull.daos.system.ICoreDataTagDao;
import yl.hs.bmipfull.daos.system.IDutyInfoDao;
import yl.hs.bmipfull.daos.system.IOrganizationInfoDao;
import yl.hs.bmipfull.daos.system.IUserInfoDao;
import yl.hs.bmipfull.pojo.material.PurchaseSystemLogEntity;
import yl.hs.bmipfull.pojo.production.ProductionDataTagEntity;
import yl.hs.bmipfull.pojo.production.ProductionDispatchLogEntity;
import yl.hs.bmipfull.pojo.salemanage.SaleContractEntity;
import yl.hs.bmipfull.pojo.salemanage.SaleSysTagsEntity;
import yl.hs.bmipfull.pojo.system.OrganizationInfoEntity;
import yl.hs.bmipfull.pojo.system.UserInfoEntity;
import yl.hs.bmipfull.service.IBaseService;
import yl.hs.bmipfull.service.impl.BaseService;
import yl.hs.bmipfull.utils.DataState;
import yl.hs.bmipfull.utils.HsApp;
import yl.hs.bmipfull.utils.Tl;
import yl.hs.bmipfull.utils.datastate.ActionType;
import yl.hs.bmipfull.utils.datastate.OrganizationUnitType;
import yl.hs.bmipfull.utils.datastate.RelationType;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SaleBaseService
 *
 * @author 谢景广
 * @category
 * @date 2021-05-17
 */
@Service
public class ProductionBaseService extends BaseService implements IBaseService {

    @Autowired
    protected IUserInfoDao userDao;
    @Autowired
    ISaleSysTagsDao salesTagsDao;
    @Autowired
    IProductionDataTagDao tagsDao;
    @Autowired
    IOrganizationInfoDao orgDao;
    @Autowired
    ICoreDataTagDao coreTagDao;
    @Autowired
    IDutyInfoDao dutyDao;


    @Autowired
    IProductionDispatchLogDao logDao;
    @Autowired
    IPurchaseSystemLogDao purlogDao;
    protected void writeSaleTag(String dataSN, String saleSN, String saleName, String oldSaleSN) {
        if (oldSaleSN != null && saleSN.equals(oldSaleSN)) {
            return;
        } else if (oldSaleSN != null && !"".equals(oldSaleSN)) {
            salesTagsDao.deleteTagByTagSNAndMainSN(dataSN, oldSaleSN);
        }
        var mapCode = Tl.getDBMapCode(SaleContractEntity.class);
        var tag = new SaleSysTagsEntity();
        tag.setMainSN(dataSN);
        tag.setMainType(mapCode);
        tag.setTagSN(saleSN);
        tag.setTagTitle(saleName);

        tag.setTagType(Tl.getDBMapCode(UserInfoEntity.class));
        tag.setState((short) 0);
        tag.setRelationType(RelationType.OWNER.toString());
        salesTagsDao.insertNew(tag);

    }

    @Override
    public Integer writeLog(ActionType action, String dataSN, String msg, String dataJson, Class<?> classType) {
        var user = HsApp.getCurrent();
        var log = new ProductionDispatchLogEntity();
        var userSN = HsApp.getClient();
        String userName = userSN;
        if (user != null) {
            userSN = user.getUserSN();
            userName = user.getUserName();
        }
        String objectName = "信息";
        DBTable dbTable = null;
        if (classType != null) {
            dbTable = classType.getAnnotation(DBTable.class);
        }


        if (dbTable != null) {
            objectName = dbTable.disName();
            log.setTypeCode(dbTable.mapCode());
            log.setTypeName(dbTable.disName());
        } else {
            log.setTypeName("系统写入");
            log.setTypeCode("SystemAutoWrite");
        }
        log.setUserSN(userSN);
        String content;
        switch (action) {
            case PRINT -> {
                content = String.format("%s打印了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case CREATE -> {
                content = String.format("%s创建了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case UPDATE -> {
                content = String.format("%s更新了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case DELETE -> {
                content = String.format("%s删除了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case EXPORT -> {
                content = String.format("%s导出了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case IMPORT -> {
                content = String.format("%s导入了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case QUERY -> {
                content = String.format("%s查询了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case UNREVIEWED -> {
                content = String.format("%s撤销审核编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case REVIEWED -> {
                content = String.format("%s审核了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            default -> {
                content = String.format("%s操作了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
        }
        log.setUserName(userName);
        log.setContent(content+(Tl.isEmpty(msg)?"":("："+msg)));
        log.setDataSN(dataSN);
        log.setDataJson(dataJson);
        log.setActionType(action.code);
        log.setHandleTime(new Date());
        return logDao.insertNew(log);
    }

    @Override
    public Integer writeLogs(ActionType action, String dataSN, String msg, String dataJson, Class<?> classType) {
        var user = HsApp.getCurrent();
        var log = new PurchaseSystemLogEntity();
        var userSN = HsApp.getClient();
        String userName = userSN;
        if (user != null) {
            userSN = user.getUserSN();
            userName = user.getUserName();
        }
        String objectName = "信息";
        DBTable dbTable = null;
        if (classType != null) {
            dbTable = classType.getAnnotation(DBTable.class);
        }


        if (dbTable != null) {
            objectName = dbTable.disName();
            log.setTypeCode(dbTable.mapCode());
            log.setTypeName(dbTable.disName());
        } else {
            log.setTypeName("系统写入");
            log.setTypeCode("SystemAutoWrite");
        }
        log.setUserSN(userSN);
        String content;
        switch (action) {
            case PRINT -> {
                content = String.format("%s打印了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case CREATE -> {
                content = String.format("%s创建了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case UPDATE -> {
                content = String.format("%s更新了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case DELETE -> {
                content = String.format("%s删除了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case EXPORT -> {
                content = String.format("%s导出了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case IMPORT -> {
                content = String.format("%s导入了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case QUERY -> {
                content = String.format("%s查询了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case UNREVIEWED -> {
                content = String.format("%s撤销审核编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            case REVIEWED -> {
                content = String.format("%s审核了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
            default -> {
                content = String.format("%s操作了编号为%s的%s信息", userName, dataSN, objectName);
                break;
            }
        }
        log.setUserName(userName);
        log.setContent(content+(Tl.isEmpty(msg)?"":("："+msg)));
        log.setDataSN(dataSN);
        log.setDataJson(dataJson);
        log.setActionType(action.code);
        log.setHandleTime(new Date());
        return purlogDao.insertNew(log);
    }

    @Override
    public void forWriteLog(String[] snList, short state) {
        var user = HsApp.getCurrent();
        String content = "";
        if (state == -2) {
            for (var str : snList) {
                writeLog(ActionType.UPDATE, str, user.getUserName() + "彻底删除了数据编号为" + str + "的数据信息", "", null);
            }
        } else {
            for (var str : snList) {
                writeLog(ActionType.UPDATE, str, user.getUserName() + "恢复删除了数据编号为" + str + "的数据信息", "", null);
            }
        }
    }

    public String getTypeCode(Class<?> type) {
        DBTable dbTable = null;
        if (type != null) {
            dbTable = type.getAnnotation(DBTable.class);
        }
        return dbTable != null ? dbTable.mapCode() : type.getName();
    }

    public String getTypeName(Class<?> type) {
        DBTable dbTable = null;
        if (type != null) {
            dbTable = type.getAnnotation(DBTable.class);
        }
        return dbTable != null ? dbTable.disName() : "信息";
    }

    public Integer writeLog(ActionType action, String[] snArray, Class<?> classType) {
        String objectName = "信息";
        var user = HsApp.getCurrent();

        DBTable dbTable = null;
        if (classType != null) {
            dbTable = classType.getAnnotation(DBTable.class);
        }
        var log = new ProductionDispatchLogEntity();
        if (dbTable != null) {
            objectName = dbTable.disName();
            log.setTypeCode(dbTable.mapCode());
            log.setTypeName(dbTable.disName());
        } else {
            log.setTypeName("系统写入");
            log.setTypeCode("SystemAutoWrite");
        }
        var userSN = HsApp.getClient();
        String userName = userSN;
        if (user != null) {
            userSN = user.getUserSN();
            userName = user.getUserName();
        }
        log.setUserSN(userSN);


        var content = String.format("%s%s了编号为(%s)的%s信息", getActionDesc(action), userName, String.join(",", snArray), objectName);
        log.setContent(content);
        log.setDataSN(String.join(",", snArray));
        log.setActionType(action.code);
        log.setHandleTime(new Date());
        return logDao.insertNew(log);
    }


    public String writeUserTag(String dataSN, Class<?> classType, String relationType) {

        //String typeCode, String title,
        var user = HsApp.getCurrent();
        if (user != null) {
            var mapCode = Tl.getDBMapCode(classType);
            SaleSysTagsEntity tag = new SaleSysTagsEntity();
            tag.setMainSN(dataSN);
            tag.setMainType(mapCode);
            tag.setTagSN(user.getUserSN());
            tag.setTagTitle(user.getUserName());

            tag.setTagType(Tl.getDBMapCode(UserInfoEntity.class));
            tag.setState((short) 0);
            tag.setRelationType(relationType);
            salesTagsDao.insertNew(tag);
            var userUnits = user.getOrganizationCode().split(",");
            var unitList = orgDao.queryBySnArray(userUnits);
            var orgCode = Tl.getDBMapCode(OrganizationInfoEntity.class);
            for (var unit : unitList) {
                tag.setTagType(orgCode);
                tag.setTagTitle(unit.getFullName());
                tag.setTagSN(unit.getSn());
                salesTagsDao.insertNew(tag);
            }
            return String.join(",", unitList.stream().map(OrganizationInfoEntity::getSn).toList());
        }
        return null;
    }

    public String writeUnitTag(String dataSN, Class<?> classType, String relationType) {

        //String typeCode, String title,
        var user = HsApp.getCurrent();
        if (user != null) {
            var mapCode = Tl.getDBMapCode(classType);
            ProductionDataTagEntity tag = new ProductionDataTagEntity();
            tag.setDataSN(dataSN);
            tag.setMainType(mapCode);
            tag.setRelationType(relationType);
            var userUnits = user.getOrganizationCode().split(",");
            var unitList = orgDao.queryBySnArray(userUnits);
            var orgCode = Tl.getDBMapCode(OrganizationInfoEntity.class);
            for (var unit : unitList) {
                tag.setTagType(orgCode);
                tag.setTagTitle(unit.getFullName());
                tag.setTagSN(unit.getSn());
                tagsDao.insertNew(tag);
            }
            return String.join(",", unitList.stream().map(OrganizationInfoEntity::getSn).toList());
        }
        return null;
    }


    public void writeDataTag(String mainSN, Class<?> classType, String tagSN, String tagTitle, Class<?> tagType, String relationType) {
        var dataType = Tl.getDBMapCode(classType);
        var tag = new ProductionDataTagEntity();
        tag.setMainType(dataType);
        tag.setDataSN(mainSN);
        tag.setTagSN(tagSN);
        var tagTypeCode = Tl.getDBMapCode(tagType);
        tag.setTagType(tagTypeCode);
        tag.setTagTitle(tagTitle);
        tag.setRelationType(relationType);
        tag.setState(DataState.CREATED.code);
        tagsDao.deleteTagByTagTypeAndRelType(mainSN, tagTypeCode, relationType);
        tagsDao.insertNew(tag);

    }

    public List<ProductionDataTagEntity> queryAllTagsBySN(String sn) {
        return tagsDao.queryAllTagsBySN(sn);
    }

    public List<ProductionDataTagEntity> queryAllTagsBySNArray(List<String> snList) {
        return tagsDao.queryAllTagsBySNList(snList);
    }

    @Override
    public String getDepartSN() {
        var user = HsApp.getCurrent();
        if (user != null) {
            var dutyList = getUserDutyList(user.getUserSN());
            var st = new ArrayList<String>();
            if (dutyList.size() > 0) {
                for (int i = 0; i < dutyList.size(); i++) {
                    var orgCode = dutyList.get(i).getOrganizationCode().split(",");
                    if (orgCode.length > 0) {
                        for (int j = 0; j < orgCode.length; j++) {
                            if (!st.contains(orgCode[j])) {
                                st.add(orgCode[j]);
                            }
                        }
                    }
                }
            }

            return String.join(",", st);
        }
        return "";
    }

    public List<String> getDepartArraySN() {
        var user = HsApp.getCurrent();
        var st = new ArrayList<String>();
        if (user != null) {
            if (user.isAdmin()) {
                st.add(user.getOrganizationCode());
                return st;
            } else {
                var dutyList = getUserDutyList(user.getUserSN());
                if (dutyList.size() > 0) {
                    for (int i = 0; i < dutyList.size(); i++) {
                        var duty = dutyList.get(i);
                        if (!st.contains(duty.getUnitSN())) {
                            st.add(duty.getUnitSN());
                        }
                    }
                }
                return st;
            }
        }
        return st;
    }

    public List<String> getCompanySNList() {
        var userSN = HsApp.getCurrent().getUserSN();
        var s = coreTagDao.queryBySN(new String[]{userSN});
        var orgCode = Tl.getDBMapCode(OrganizationInfoEntity.class);
        var unitSn = s.stream().filter(p -> p.getTagType().equals(orgCode) && p.getMainSN().equals(userSN)).map(p -> p.getTagSN()).collect(Collectors.toList());
        var orgList = orgDao.queryBySnArray(unitSn.toArray(new String[unitSn.size()]));
        var allOrgSNList = new ArrayList<String>();
        for (int i = 0; i < orgList.size(); i++) {
            var orgCodes = orgList.get(i).getParentCode().split(",");
            if (orgCodes.length > 0) {
                for (int j = 0; j < orgCodes.length; j++) {
                    if (!allOrgSNList.contains(orgCodes[j])) {
                        allOrgSNList.add(orgCodes[j]);
                    }
                }
            }
        }
        var allOrgList = orgDao.queryBySnArray(allOrgSNList.toArray(new String[allOrgSNList.size()]));
        allOrgSNList.clear();
        if (allOrgList.size() > 0) {
            for (int i = 0; i < allOrgList.size(); i++) {
                var org = allOrgList.get(i);
                if (org.getOrganizationType() == OrganizationUnitType.Company.code) {
                    if (!allOrgSNList.contains(org.getSn())) {
                        allOrgSNList.add(org.getSn());
                    }
                }
            }
        }
        return allOrgSNList;
    }
}
